#include "AnimationInfo.h"


double LinearFunction::GetY(double x)
{
	double ret = 0.0;

	int i = 0;
	for(; i < vecPos.size()-1 ; i ++)
	{
		_POSITION &p1 = vecPos[i];
		_POSITION &p2 = vecPos[i+1];

		if(p1.GetX() <= x && x <= p2.GetX())
		{
			double dec =  (p2.GetY() - p1.GetY()) / (p2.GetX() - p1.GetX());
			ret = dec * (x - p1.GetX()) + p1.GetY();

			break;
		}
	}

	ACE_ASSERT(i < vecPos.size()-1);

	return ret;
}


bool AnimationInfo::CalcAnimation(Json::Value & animation_info)
{
	std::string target = PACKET_BASE::GetStringS(animation_info , "targetProperty");

	if("alpha" == target)
		return CalcAlpha(animation_info);
	else if("transform" == target)
		return CalcTransform(animation_info);

	return false;
}

bool AnimationInfo::CalcAlpha(Json::Value & alpha_info)
{
	if(frame_count == 0)
		return false;


	const double total_start = init_info.GetTime().GetStart();
	const double total_duration = init_info.GetTime().GetDuration();


	Json::Value &alpha_time = alpha_info["keyTimes"];
	Json::Value &alpha_value = alpha_info["values"];

	if(alpha_time.size() > 0 && alpha_time.size() == alpha_value.size())
	{
		double compTime = -1.0;
		std::vector<_POSITION> vecValues;
		for(int i = 0 ; i < alpha_time.size() ; i ++)
		{
			double alphaTime = alpha_time[i].asDouble();

			if(i == 0 && 0.0 != alphaTime)
			{
				_POSITION pos_first(total_start	, init_info.GetAlpha());
				vecValues.push_back(pos_first);

				compTime = 0.0;
			}

			if(alphaTime >= 0.0 && alphaTime <= 1.0 && compTime < alphaTime)
			{
				_POSITION pos(total_start + alphaTime * total_duration 
							, alpha_value[i].asDouble());

				vecValues.push_back(pos);

				if(1.0 == alphaTime)
					break;

				compTime = alphaTime;
			}

			if(i == alpha_time.size() - 1 && 1.0 != alphaTime)
			{
				_POSITION pos_last(total_start + total_duration	, alpha_value[i].asDouble());
				vecValues.push_back(pos_last);
			}
		}


		LinearFunction alphaFunc(vecValues);

		for(int i = 0 ; i < frame_count ; i ++)
		{
			double frame_start_time = total_start + i * Settings::GetSettings()->FRAME_INTERVAL; 
			double frame_alpha_value = alphaFunc.GetY(frame_start_time); 

			frame_list[i].GetTime().SetStart(frame_start_time);
			frame_list[i].GetTime().SetDuration(Settings::GetSettings()->FRAME_INTERVAL);
			frame_list[i].SetAlpha(frame_alpha_value);
		}

	}
	else
	{
		printf("animation alpha count mismatch : time[%d]  !=  value[%d]\n" ,  alpha_time.size() , alpha_value.size());
		return false;
	}


	return true;
}


bool AnimationInfo::CalcTransform(Json::Value & trans_info)
{
	if(frame_count == 0)
		return false;

	const double total_start = init_info.GetTime().GetStart();
	const double total_duration = init_info.GetTime().GetDuration();


	Json::Value &trans_time = trans_info["keyTimes"];
	Json::Value &trans_value = trans_info["values"];

	if(trans_time.size() > 0 && trans_time.size() == trans_value.size())
	{
		std::vector<_POSITION> vec_width;
		std::vector<_POSITION> vec_height;

		std::vector<_POSITION> vec_rotation;

		std::vector<_POSITION> vec_x;
		std::vector<_POSITION> vec_y;

		double compTime = -1.0;

		for(int i = 0 ; i < trans_time.size() ; i ++)
		{
			double transTime = trans_time[i].asDouble();

			if(i == 0 && 0.0 != transTime)
			{
				vec_width.push_back(_POSITION(total_start	, init_info.GetSize().GetWidth()) );
				vec_height.push_back(_POSITION(total_start	, init_info.GetSize().GetHeight()) );

				vec_rotation.push_back(_POSITION(total_start	, init_info.GetRotation()) );

				vec_x.push_back(_POSITION(total_start	, init_info.GetPosition().GetX()) );
				vec_y.push_back(_POSITION(total_start	, init_info.GetPosition().GetY()) );

				compTime = 0.0;
			}

			double time = total_start + transTime * total_duration;
			_POSITION pos_width( time , PACKET_BASE::GetDoubleS(trans_value[i] , "scale" , "xScale") * init_info.GetSize().GetWidth());
			_POSITION pos_height( time , PACKET_BASE::GetDoubleS(trans_value[i] , "scale" , "yScale") * init_info.GetSize().GetHeight());

			_POSITION pos_rotation( time , PACKET_BASE::GetDoubleS(trans_value[i] , "rotation") + init_info.GetRotation());

			_POSITION pos_x( time , PACKET_BASE::GetDoubleS(trans_value[i] , "translation" , "x") + init_info.GetPosition().GetX());
			_POSITION pos_y( time , PACKET_BASE::GetDoubleS(trans_value[i] , "translation" , "y") + init_info.GetPosition().GetY());


			if(transTime >= 0.0 && transTime <= 1.0 && compTime < transTime)
			{
				vec_width.push_back(pos_width);
				vec_height.push_back(pos_height);

				vec_rotation.push_back(pos_rotation);

				vec_x.push_back(pos_x);
				vec_y.push_back(pos_y);

				if(1.0 == transTime)
					break;

				compTime = transTime;
			}



			if(i == trans_time.size() - 1 && 1.0 != transTime)
			{

				vec_width.push_back(_POSITION(total_start + total_duration	, pos_width.GetY()) );
				vec_height.push_back(_POSITION(total_start + total_duration	, pos_height.GetY()) );

				vec_rotation.push_back(_POSITION(total_start + total_duration	, pos_rotation.GetY()) );

				vec_x.push_back(_POSITION(total_start + total_duration	, pos_x.GetY()) );
				vec_y.push_back(_POSITION(total_start + total_duration	, pos_y.GetY()) );

			}
		}

		LinearFunction widthFunc(vec_width);
		LinearFunction heightFunc(vec_height);

		LinearFunction rotationFunc(vec_rotation);

		LinearFunction xFunc(vec_x);
		LinearFunction yFunc(vec_y);

		for(int i = 0 ; i < frame_count ; i ++)
		{
			double frame_start_time = total_start + i * Settings::GetSettings()->FRAME_INTERVAL; 

			double frame_width = widthFunc.GetY(frame_start_time); 
			double frame_height = heightFunc.GetY(frame_start_time); 

			double frame_rotation = rotationFunc.GetY(frame_start_time); 

			double frame_x = xFunc.GetY(frame_start_time); 
			double frame_y = yFunc.GetY(frame_start_time); 


			frame_list[i].SetTime(_TIME(frame_start_time , Settings::GetSettings()->FRAME_INTERVAL));

			frame_list[i].SetSize(_SIZE(frame_width , frame_height) );
			frame_list[i].SetRotation(frame_rotation);
			frame_list[i].SetPosition(_POSITION(frame_x , frame_y) );



			

		}

	}
	else
	{
		printf("animation trans count mismatch : time[%d]  !=  value[%d]\n" ,  trans_time.size() , trans_value.size());
		return false;
	}


	return true;
}



